#include "GLInputManager.h"
#include "GLKeyboardEvent.h"
namespace mp_gl
{

		GLInputManager::GLInputManager(GLFWwindow* window)
			:Updateable()
		{
			//Set the listening window
			m_window = window;

			//Create the button press event collection
			m_inputBindCollection = new GLButtonEventCollection();

			//Allocate the direct keyboard listener array
			m_directKeyInputCount = 0;
			m_directKeyInputs = new 
				GLDirectKeyboardInput*[MPGL_DEF_DIRECTKEY_LISTENETS];
			for(unsigned int i = 0; i < m_directKeyInputCount; i++)
				m_directKeyInputs[i] = NULL;
		}
		

		GLInputManager::~GLInputManager(){

			//Delete the input bind array, though since elements in the 
			// array are passed in externally, we will delete just 
			// the array and not the elements in the the array.
			delete [] m_directKeyInputs;
		}
		

		void GLInputManager::Initialize(){

			//Set the windows user pointer to the input manager
			glfwSetWindowUserPointer(m_window, this);
			//Bind direct keyboard char input
			BindDirectKeyboardListener();
		}
		

		void GLInputManager::Update(){

			while(!m_inputBindCollection->TryLock()){;;}
			//Loop through input collection using an iterator
			for(std::vector<spGLButtonEvent>::iterator 
				it = m_inputBindCollection->begin();
				it < m_inputBindCollection->end(); 
				it++)
			{
				(*it)->Update(m_window);
			}
			m_inputBindCollection->Unlock();
		}
		

		void GLInputManager::Uninitialize()
		{
			

		}


		void GLInputManager::AddDirectKeyboardListener
			(GLDirectKeyboardInput* listener)
		{
			//If we are adding to a full array
			if ( m_directKeyInputCount >= MPGL_DEF_DIRECTKEY_LISTENETS )
			{
				//Allocate a temp array with one extra node
				GLDirectKeyboardInput** tmp =
					new GLDirectKeyboardInput *
						[++m_directKeyInputCount];
				//Copy all the nodes pointers to the new array
				for(unsigned int i = 0; i < 
					(m_directKeyInputCount-2); i++)
				{
					tmp[i] = m_directKeyInputs[i];
				}
				//In the last array location, set the newly added node
				m_directKeyInputs[m_directKeyInputCount-1] = listener;

			}
			//If we have array space
			else
			{
				
				m_directKeyInputs[m_directKeyInputCount++] = listener;
			}
		}


		void GLInputManager::BindDirectKeyboardListener()
		{
			glfwSetCharCallback(m_window, GLInputManager::KeyCharEvent);
		}


		void GLInputManager::KeyCharEvent(GLFWwindow* window, unsigned int key)
		{
			//Send the event to the local handler via the windows user pointer
			GLInputManager* im = ((GLInputManager*)glfwGetWindowUserPointer(window));
			im->SendGLDirectKeyboardEvent(key);
		}


		void GLInputManager::SendGLDirectKeyboardEvent(unsigned int key)
		{
			for(unsigned int i = 0; i < m_directKeyInputCount; i++)
			{
				m_directKeyInputs[i]->push(key);

			}
		}
		
}